/*
 * Project: Sudoku Solver
 * File: cell.h
 *
 * Copyright (C) 2009 Daniel Meekins
 * Contact: dmeekins - gmail
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef CELL_H
#define CELL_H

#include <stdlib.h>
#include <stdint.h>

#define CELL_MAX_NUM 9

struct cell
{
    uint32_t num:CELL_MAX_NUM;
};

typedef struct cell cell_t;

/*
 * Creates a new cell object initialized with the specified number. If the
 * passed number is 0, the cell is initialized with all possibilities.
 */
cell_t *cell_new(uint32_t num);

/*
 * Sets the number for the passed cell. Has the same behavior as cell_new
 * when num is 0.
 */
void cell_set_num(cell_t *c, uint32_t num);

/*
 * Sets all the possibilities in the cell.
 */
void cell_set(cell_t *c);

/*
 * Clears all the possibilities in the cell.
 */
void cell_clear(cell_t *c);

/*
 * Returns the number of the passed cell, or 0 if there is more than one
 * possibility.
 */
uint32_t cell_get_num(cell_t *c);

/*
 * Each index in the passed num_count is incremented if that number is possible
 * in the cell.
 */
void cell_fill_possible_num_count(cell_t* c, uint32_t num_count[CELL_MAX_NUM]);

/*
 * Returns the number of possible numbers the cell could be.
 */
uint32_t cell_possible_count(cell_t *c);

/*
 * Adds the possibilities from the cell poss to the cell dst.
 */
void cell_add_possible_nums(cell_t *dst, cell_t *poss);

/*
 * Removes the possibile numbers in poss from the cell dst if it isn't
 * solved yet.
 */
void cell_remove_possible_nums(cell_t *dst, cell_t *poss);

/*
 * Takes the sets of possible numbers from c1 and c2 and stores the
 * intersection of the two sets in cell c.
 */
void cell_intersect(cell_t *c, cell_t *c1, cell_t *c2);

/*
 * Takes the sets of possible numbers from c1 and c2 and stores the
 * union of the two sets in cell c.
 */
void cell_union(cell_t *c, cell_t *c1, cell_t *c2);

/*
 * Takes the possible numbers from c1 and c2 and "XOR" the two cells.
 */
void cell_diff(cell_t *c, cell_t *c1, cell_t *c2);

/*
 * Inverts the possibilities of the possible numbers in the cell. 
 */
void cell_invert(cell_t *c);

/*
 * Copies the possibilities from the cell src to the cell dst.
 */
void cell_copy(cell_t *dst, cell_t *src);

/*
 * Returns 1 if the num is possible in the cell c, and 0 otherwise.
 */
int cell_num_ispossible(cell_t *c, uint32_t num);

/*
 * Returns 1 if the passed cell has only one possibility, and 0 otherwise.
 */
int cell_issolved(cell_t *c);

/*
 * Returns 1 if the two cells have the same number possibilities.
 */
int cell_isequal(cell_t *c1, cell_t *c2);

/*
 * Frees the memory used by the passed allocated cell.
 */
void cell_free(cell_t *c);

/* for debugging */
char *cell_num_string(cell_t *c);

#endif /* CELL_H */
